/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package interfaceAndController;

import editingDistance.Algorithm;
import findAntlrRules.AntlrRule;
import findAntlrRules.FindAntlrRules;
import findAntlrRules.Pereche;
import findAntlrRules.RewriteInfo;
import generateAndLoadClasses.CompileGrammar;
import gettree.Tree;
import gettree.TreeNode;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import antlr.debug.NewLineEvent;

import treeView.TreeView;

import checkInputType.TryReturn;


import Utils.Proprietati;
import Utils.ReplaceInFile;


/**
 *
 * @author daniel
 */
public class Controller {
	public static StringBuffer strTime= new StringBuffer();
	public static ArrayList<String> covRules = new ArrayList<String>();
	// store the list of rules
	public static ArrayList<AntlrRule> orderedRuleList = new ArrayList<AntlrRule>();
	// store the list of subrules that match a token
	public static ArrayList<String> simpleRules = new ArrayList<String>();
	public static final String options = "options\n"
			+ "{\n"
			+ "	backtrack = true;\n"
			//+ "	k=6;\n"
			+ "	output = AST;\n"
			+ "}\n"; 
	public static ArrayList<TreeNode> mostWr = new ArrayList<TreeNode>();
	public static ArrayList<TreeNode> processed =  new ArrayList<TreeNode>();

	public static HashMap<Integer, ArrayList<Pereche>> dists = new HashMap<Integer,ArrayList<Pereche>>();
	public static HashMap<Integer, Pereche> distsMinim = new HashMap<Integer,Pereche>();

	/**
	 * Parse input grammar to get orderred list of grammar rules 
	 * Generate modified gramar files (one with just code for indentifying the rule used when parse input 
	 *                                 one with simplified ast )
	 * Generate java classes (using antlr ) from modified grammar files
	 * Generate class file used to parse input and generate ast  
	 * @param grammarFile file containing the language definition 
	 */

	public static void loadGrammarFile(File grammarFile) throws FileNotFoundException, IOException, Exception{
		
		strTime= new StringBuffer();
		long time = System.currentTimeMillis();
		long time2 = System.currentTimeMillis();
		// without any rewrite rules
		File tr2 = transformGrammar.TransformGrammar.addGetParsedTree(grammarFile);
		strTime.append("Timp necesar modificarii gramaticii : " + (System.currentTimeMillis() -time2)+"\n");
		
		time2 = System.currentTimeMillis();
		CompileGrammar.generateJavas(tr2.getPath());
		strTime.append("Timp necesar generarrii fisierelor java : " + (System.currentTimeMillis() -time2)+"\n");
		time2 = System.currentTimeMillis();
		CompileGrammar.compileClasses(Proprietati.genJavaOut+"\\*.java");
		strTime.append("Timp necesar compilarii fisierelor java : " + (System.currentTimeMillis() -time2)+"\n");
		
		time2 = System.currentTimeMillis();
		findAntlrRules.FindAntlrRules.getOrderedRules(grammarFile.getPath());
		
		orderedRuleList=findAntlrRules.FindAntlrRules.orderedRuleList;
		Proprietati.grammarFile =grammarFile.getName().substring(0, grammarFile.getName().indexOf("."));

		// analize subrules for each rule and decide if it matches a token
		for (AntlrRule rule : orderedRuleList){
			String [] sRules = rule.getSubRules(); 
			for (int i = 0 ; i< sRules.length ; i++){
				if (isSimpleRule(sRules[i])){
					simpleRules.add(rule.getName()+"_"+i);
				}
			}
		}
		strTime.append("Timp necesar analizarii gramaticii java : " + (System.currentTimeMillis() -time2)+"\n");
		time= System.currentTimeMillis() -time;
		strTime.append("Timp necesar incarcarii gramaticii :" + time+"\n");
		strTime.append("numarul total de reguli : " + orderedRuleList.size()+"\n");
	}

	/**
	 * Add rewrite information to specific rule
	 * @param index index of rule
	 * @param info rewrite information to be aded to rule 
	 */ 
	public static void addTreeToRule(int index, RewriteInfo info) {
		orderedRuleList.get(index).addToPosRewrites(info);
	}

	
	public static void countCovRules(TreeNode n ){
		for (int i = 0 ; i < n.getChildCount();i++)
			countCovRules(n.getChild(i));
		if (!covRules.contains(n.getLabel()))
			covRules.add(n.getLabel());
		
	}
	
	/**
	 * Find the rule used to parse input, find input rule if selected one is incorrect
	 *      Transform textual representation of AST in tree representation
	 *      Store the rewrite information for rule used to parse input for furder analyse
	 * 
	 * @param textAst textual representation of the ast for current selected rule
	 * @param selectedRule current selected rule
	 * @param toParse textula input to parse for finding which rules were used to parse input
	 * @param ruleIndex the rule index in list
	 * @return -1 if the input could not be parsed
	 *          the intex in stored list of the rule used to parse input 
	 * @throws Exception 
	 */
	public static int analizeInput(String textAst, AntlrRule selectedRule,String toParse,int ruleIndex) throws Exception{
		strTime = new StringBuffer();
		dists.clear();
		mostWr.clear();
		//
		processed.clear();	
		long time = System.currentTimeMillis();
		long time2 = System.currentTimeMillis();
		gettree.Tree t = gettree.GetTree.getTree(textAst, "(", ")", "`", ",");
		strTime.append("Timp necesar construirii arborelui ast : " + (System.currentTimeMillis() -time2)+"\n");
		time2 = System.currentTimeMillis();
		int i;

		TryReturn ret ; 
		TreeNode tn = t.getRoot();
		if ((ret = checkInputType.GetInputType.tryType(Proprietati.grammarFile, selectedRule.toString(), toParse)).isMatched()) {
			strTime.append("Timp necesar generarii PT : " + (System.currentTimeMillis() -time2)+"\n");
			covRules.clear();
			countCovRules(ret.getTree().getRoot());
			strTime.append("*******\n numar de subreguli acoperite : " + covRules.size());
			for (int o = 0 ; o < covRules.size();o++)
				strTime.append("\t"+covRules.get(o)+"\n");
			time2 = System.currentTimeMillis();
			//RewriteInfo info = new RewriteInfo();
			//info.setRuleNr(ret.getTree().getRoot().getChild(0).getLabel());
			//info.setTree(t);
			//info.setPtree(ret.getTree());
			//info.setInputString(toParse);
			//addTreeToRule(ruleIndex,info);
			//ReturnAst ret2 = findtinputype.GetInputType.getAst(Properties.grammarFile, selectedRule.toString(), toParse);
			//System.out.println(" ************** Arborele de parsare de dinainte de stergerea nodurilor neproductive  ******** ");
			//printTree(ret.getTree().getRoot(),1);
			removeUnproductiveRules(ret.getTree().getRoot());
			strTime.append("Timp necesar eliminarii reguli neproductive  : " + (System.currentTimeMillis() -time2)+"\n");
			time2 = System.currentTimeMillis();
			//.out.println(" ************** Arborele de parsare de dupa de stergerea nodurilor neproductive  ******** ");
			//printTree(ret.getTree().getRoot(),1);
			removeLeafs(t.getRoot());
			strTime.append("Timp necesar eliminarii frunzelor fin ast : " + (System.currentTimeMillis() -time2)+"\n");
			time2 = System.currentTimeMillis();
			//System.out.println(" AST ");
			//printTree(t.getRoot(),1);
			try{
				sincStructures(ret.getTree().getRoot(), t.getRoot());
			}catch (Exception e) {
				int k =0 ; k++;
			}
			//printTree(ret.getTree().getRoot(),1);
			strTime.append("Timp necesar sincronizarii arborelui: " + (System.currentTimeMillis() -time2)+"\n");
			time2 = System.currentTimeMillis();
			//System.out.println(" ************** Arborele de parsare de dupa de stergerea nodurilor neproductive  ******** ");
			//printTree(ret.getTree().getRoot(),1);
			analizeTrees( ret.getTree().getRoot(),t.getRoot());
			strTime.append("Timp necesar analizarii celor doi arbori : " + (System.currentTimeMillis() -time2)+"\n");
			time2 = System.currentTimeMillis();
			analyze();
			strTime.append("Timp necesar analizarii infomatiilor dobandite : " + (System.currentTimeMillis() -time2)+"\n");
			time2 = System.currentTimeMillis();
			//panel.loadTree(ret.getTree().getRoot());
			/*if (tn.getChildCount() ==1 ){}
			//recursiveAdd(t.getRoot().getChild(0), ret.getAppRules());
			else {
				ArrayList<TreeNode> nl = tn.getChildrens();
				ArrayList<TreeNode> sc = new ArrayList<TreeNode>();
				TreeNode ct = nl.remove(0); 
				sc.add(ct);
				tn.setChildrens(sc);
				for (; 0 < nl.size();){
					TreeNode tnc = nl.remove(0);
					for(;!ct.isLeaf();ct = ct.getChild(ct.getChildCount()-1));
					mostWr.add(ct);
					tnc.setParent(ct);
					ct.addChild(tnc);
					ct=tnc;
				}
				tar = gettree.Main.stringTree(t.getRoot(), 1);
				//recursiveAdd(t.getRoot().getChild(0), ret.getAppRules());
			}
			//System.out.println("\n\n\n*********\nAu mia ramas " +ret.getAppRules().size());*/
			return ruleIndex;
		}
		for (i = orderedRuleList.size(); i > 0; i--) {
			if ((ret = checkInputType.GetInputType.tryType(Proprietati.grammarFile, orderedRuleList.get(i - 1).toString(), toParse)).isMatched()) {
				RewriteInfo info = new RewriteInfo();
				info.setTree(t);
				info.setRuleNr(ret.getTree().getRoot().getChild(0).getLabel());
				info.setPtree(ret.getTree());
				info.setInputString(toParse);
				addTreeToRule(i - 1, info);
				//ReturnAst ret2 = findtinputype.GetInputType.getAst(Properties.grammarFile, orderedRuleList.get(i - 1).toString(), toParse) ;
				removeUnproductiveRules(ret.getTree().getRoot());
				removeLeafs(t.getRoot());
				sincStructures(ret.getTree().getRoot(), t.getRoot());
				analizeTrees(ret.getTree().getRoot(),t.getRoot());
				analyze();
				//panel.loadTree(ret.getTree().getRoot());
                                /*
				if (tn.getChildCount() ==1 )
				{}//recursiveAdd(t.getRoot().getChild(0), ret.getAppRules());
				else {
					ArrayList<TreeNode> nl = tn.getChildrens();

					ArrayList<TreeNode> sc = new ArrayList<TreeNode>();
					TreeNode ct = nl.remove(0); 
					sc.add(ct);
					tn.setChildrens(sc);
					for (; 0 < nl.size();){
						TreeNode tnc = nl.remove(0);
						for(;!ct.isLeaf();ct = ct.getChild(ct.getChildCount()-1));
						tnc.setParent(ct);
						ct.addChild(tnc);
						ct=tnc;
					}
				}
				tar = gettree.Main.stringTree(t.getRoot(), 1);
				//recursiveAdd(t.getRoot().getChild(0), ret.getAppRules());;
				 */
				return i-1;
			}
		}
		return  -1;
	}
	/**
	 * 
	 * Start to analize stored information to construct ast form given examples
	 * @throws Exception 
	 */
	public static void analyze() throws Exception{
		AntlrRule.analyze();

	}

	private static void removeUnproductiveRules (TreeNode pt ){
		if (pt.getLabel().contains("decl")){
			int g=0;
			g++;
		}
 		if (pt.getLabel().trim().isEmpty()){
			for (int i = 0 ; i < pt.getChildCount() ; i++)
				removeUnproductiveRules(pt.getChild(i));
			return;
		}
 		if (pt.getLabel().equals("stmts_0"))
		{
			int o = 0;
			o++;
		}
		String rule = pt.getLabel().substring(0, pt.getLabel().lastIndexOf("_"));
		// find the AntlrRule to witch the tree shoul be added in ordered list
		int index = 0 ;
		for(; index< orderedRuleList.size(); index++){
			if (orderedRuleList.get(index).getName().equals(rule))
				break;
		}
		if (index== orderedRuleList.size())
			return;
		String appSubrule = pt.getLabel().substring(pt.getLabel().lastIndexOf("_")+1);
		int nrsubR = Integer.parseInt(appSubrule);
		String rule2 = stripSubruleNr( pt.getChildCount() > 0 ? pt.getChild(0).getLabel() : "");
		String subRBody = stripBeforeChar(orderedRuleList.get(index).getSubRules()[nrsubR],';');
		if (rule2.trim().equals(subRBody.trim()) || (isRecursive(orderedRuleList.get(index).getSubRules()[nrsubR]) && pt.getChildCount()==1 ) 
				|| (isSimpleRule(orderedRuleList.get(index).getSubRules()[nrsubR])&& pt.getChildCount()>0 && !subRBody.contains("'")) 
				|| (orderedRuleList.get(index).getSubRules()[nrsubR].trim().equals(transformGrammar.TransformGrammar.constructTreeWLabel(orderedRuleList.get(index).getSubRules()[nrsubR]).trim() )&& !orderedRuleList.get(index).getSubRules()[nrsubR].equals(orderedRuleList.get(index).getSubRules()[nrsubR].toUpperCase()))){
			((TreeNode)pt.getParent()).deleteChAndReplace(pt);
		}
		for (int i = 0 ; i < pt.getChildCount() ; i++)
			removeUnproductiveRules(pt.getChild(i));
	}

	private static void removeLeafs(TreeNode t ){
		for (int i = 0 ; i < t.getChildCount();i++)
			if (t.getChild(i).isLeaf())
				t.deleteChild(i);
		for (int i = 0 ; i < t.getChildCount();i++)
			removeLeafs(t.getChild(i));
	}

	public static void sincStructures(TreeNode pt , TreeNode ast){
		// resetarea distantelor calculate anterior
		dists.clear();
		distsMinim.clear();
		// compararea nodului curent din AST cu nodurile de pe acelasi nivel din parse tree
		for (int i =0 ; i < ast.getChildCount();i++){
			ArrayList<Pereche> list =  new ArrayList<Pereche>();
			Pereche minim = null;
			for (int j =0 ; j< pt.getChildCount();j++){
				// verifica daca inaltimea arborilor cu inaltimea in nodurile curent comparate este aceeasi
				if (ast.getChild(i).getH() == pt.getChild(j).getH())
					if (minim == null )
						minim = new Pereche(j,Algorithm.doWork(pt.getChild(j), ast.getChild(i)));
					else {
						// calculeaza distanta de editare dintre cei doi subarbori si memoreaza aceasta rezultatul
						Pereche curent = new Pereche(j,Algorithm.doWork(pt.getChild(j), ast.getChild(i)));
						// verifica minimul
						if (curent.getDist() < minim.getDist()){
							list.add(minim);
							minim= curent;
						}
						else
							list.add(curent);
					}
			}
			// memoram minimul gasit si lista distantelor
			distsMinim.put(i,minim) ;
			dists.put(i, list);
		}
		// asupra acestui nod vom efectua schimbarile de structura
		TreeNode nodeSinc = new TreeNode(null, pt.getLabel(), pt.getChildrens());
		for (int i = 0 ; i < ast.getChildCount(); i++){
			// daca lista este vida, inseamna ca nodul din AST nu a avut decat un nod cu aceeasi inaltime in parse tree
			if(dists.get(i).isEmpty()){
				// verificam daca indicele nodului a fost schimbat in AST
				if (i!=distsMinim.get(i).getPozitie()){
					// schimbam indicele 
					//nodeSinc.deleteChild(distsMinim.get(i).getPozitie());
					//nodeSinc.addChild(pt.getChild(distsMinim.get(i).getPozitie()), i);
					ast.getChild(i).setOldP(distsMinim.get(i).getPozitie());
				}
			}
			// cautam nodurile cu care exista conflicte
			else
			{
				Pereche min = distsMinim.get(i);
				// indicele nodului ce are cea mai mica distanta 
				int idxMinD = i;
				// cautam indicele cu cea mai mica distanta 
				for (int j = i+1 ; j < ast.getChildCount();j++ ){
					// sarim peste nodurile ce au deja un corespondent in arbore
					if (ast.getChild(j).getOldP()!=-1)
						continue;
					Pereche minJ = distsMinim.get(j);
					if (min.getPozitie() == minJ.getPozitie())
						if (min.getDist()==minJ.getPozitie()){
							//askUser(ast,pt,idxMinD,j,min.getPozitie());
						}
					// calculul distantei minime
					if (min.getDist()>minJ.getPozitie()){
						distsMinim.remove(idxMinD);
						distsMinim.put(idxMinD,getAndRemoveMinim(dists.get(idxMinD)));
						idxMinD = j ;
					}
				}
				// memorarea corespondentei gasite
				if (idxMinD!=distsMinim.get(idxMinD).getPozitie()){
					// schimbam indicele 
					//nodeSinc.deleteChild(distsMinim.get(idxMinD).getPozitie());
					//nodeSinc.addChild(pt.getChild(distsMinim.get(idxMinD).getPozitie()), idxMinD);
					ast.getChild(idxMinD).setOldP(distsMinim.get(idxMinD).getPozitie());
				}
				// verifica daca nodul curent a fost mapat
				if (idxMinD!=i)
					i--;
			}
		}
		for(int i = 0; i< ast.getChildCount();i++){
			sincStructures(pt.getChild(i),ast.getChild(i));
		}
	}

	public static Pereche getAndRemoveMinim (ArrayList<Pereche> list){
		if (list.size()==0)
			return null;
		Pereche rez = list.get(0);
		int index=0;
		for (int i = 0 ; i < list.size() ;i++){
			if (rez.getDist() < list.get(i).getDist())
			{	
				index = i  ;
				rez=list.get(i);
			}

		}
		list.remove(index);
		return rez;
	}

	/*
	 * Parcurgem arborii (ce au fost deja sincronizati)simultan ceo doi arbori di 
	 */
	private static void analizeTrees(TreeNode pt , TreeNode ast  ){

		// analizeaza nodul curent
		try{
		//extrace regula din gramatica folosita in parsare
			if (pt.getLabel().equals("decl"))
			{
				int o = 0;
				o++;
			}
			if (pt.getLabel().isEmpty()){
				for (int i = 0 ; i< pt.getChildCount();i++)
				{
					analizeTrees(pt.getChild(i) , ast.getChild(i)  );
					
				}
				return;
			}
		String rule = pt.getLabel().substring(0, pt.getLabel().lastIndexOf("_"));
		// cauta aceasta refula pe baza numelui sau in lista de reguli 
		int index = 0 ;
		for(; index< orderedRuleList.size(); index++){
			if (orderedRuleList.get(index).getName().equals(rule))
				break;
		}
		if (index== orderedRuleList.size())
			return;
		// creeaza obiectul ce va retine informatiile despre rescriere
		RewriteInfo r = new RewriteInfo();
		// seteaza subregula folosita
		r.setRuleNr(pt.getLabel());

		// adauga arborele ast
		Tree t = new Tree();
		t.getRoot().addChild(ast);
		r.setTree(t);
		t = new Tree();
		t.getRoot().addChild(pt);
		r.setPtree(t);
		
		/*
		 * RewriteInfo info = new RewriteInfo();
			info.setRuleNr(ret.getTree().getRoot().getChild(0).getLabel());
			info.setTree(t);
			info.setPtree(ret.getTree());
			info.setInputString(toParse);
			addTreeToRule(ruleIndex,info);
		 */

		//adauga rescrierea la lista de rescrieri a regulii utilizate
		addTreeToRule(index, r);

		// apeleaze recursiv analiza nodurilor
		for (int i = 0 ; i < ast.getChildCount(); i++)
		{
			analizeTrees(pt.getChild(i),ast.getChild(i));
		}
		
		}catch (Exception e) {
			int i =0 ;
			i++;
		}
	}

	/**
	 * Generate output grammar file 
	 * @param parentDirectory directory where to put generate grammar file  
	 */
	public static HashMap<String, String> writeToFile(File parentDirectory) throws IOException{
		// contruct token map
		long time = System.currentTimeMillis();
		HashMap<String, String> map = new HashMap<String, String>();
		ArrayList< String> tokens = new ArrayList<String>();
		StringBuffer tokensString = new StringBuffer("tokens{\n");
		for(AntlrRule r : orderedRuleList){
			String rName = r.getName();
			int i = 0 ;
			for (String label : r.getLabels()){
				if (label.trim().isEmpty())
					continue;
				if (!tokens.contains(label.subSequence(0,label.lastIndexOf("///") ).toString().trim())){
					String l = label.subSequence(0,label.lastIndexOf("///") ).toString().trim();
					tokens.add(l);
					tokensString.append("\t"+rName.toUpperCase().trim()+"_"+i+"='"+l+"';\n");
					map.put("\""+rName.toUpperCase().trim()+"_"+i+"\"", "\""+l+"\"");
				}
				i++;
			}
		}
		tokensString.append("}\n");

		FileWriter fstream = new FileWriter(parentDirectory.getPath()+"\\"+Proprietati.grammarFile+".g");
		BufferedWriter out = new BufferedWriter(fstream);
		out.write("grammar "+Proprietati.grammarFile+";\n");
		out.write(options);
		out.write(tokensString.toString());
		// write pout the rewrite rules;
		for (int i = 0 ; i < orderedRuleList.size();i++){
			AntlrRule r = orderedRuleList.get(i);
			out.write(r.constructRR()+"\n");
		}
		//write out the tokens rules
		for (int i = 0 ; i< FindAntlrRules.tokenList.size();i++){
			out.write(FindAntlrRules.tokenList.get(i).getGrammarRule()+"\n");
		}
		out.flush();
		out.close();
		System.out.println("time to generate fis out :" + (System.currentTimeMillis()-time));
		return map ;
	}

	public static String stripSubruleNr(String s){
		return stripBeforeChar(s, '_');
	}

	public static String stripBeforeChar(String s,char c ){
		return s.lastIndexOf(c)==-1?s.trim():s.substring(0,s.lastIndexOf(c)).trim();
	}

	public static String stripOptRule (String s){
		String [] comp = s.split(" ");
		StringBuffer rez = new StringBuffer();
		for (int i =0 ; i < comp.length ; i++){
			if (comp[i].contains("?"))
				continue;
			rez.append(comp[i]+"");
		}
		return rez.toString();
	}

	public static boolean isSimpleRule(String srule){
		if ((srule.trim().startsWith("'") && srule.trim().endsWith("'") && srule.trim().split("'").length==2) || (srule.equals(srule.toUpperCase())&&!srule.trim().isEmpty()))
			return true;
		return false;
	}

	public static void copyDirectory(File sourceLocation , File targetLocation)
			throws IOException {

		if (sourceLocation.isDirectory()) {
			if (!targetLocation.exists()) {
				targetLocation.mkdir();
			}

			String[] children = sourceLocation.list();
			for (int i=0; i<children.length; i++) {
				copyDirectory(new File(sourceLocation, children[i]),
						new File(targetLocation, children[i]));
			}
		} else {

			InputStream in = new FileInputStream(sourceLocation);
			OutputStream out = new FileOutputStream(targetLocation);

			// Copy the bits from instream to outstream
			byte[] buf = new byte[1024];
			int len;
			while ((len = in.read(buf)) > 0) {
				out.write(buf, 0, len);
			}
			in.close();
			out.close();
		}
	}

	public static void generateJar(File file,String topFunction) throws IOException{
		//System.out.println(System.getProperty("java.io.tmpdir"));
		
		File f = new File(System.getProperty("java.io.tmpdir")+"outputJava\\"+System.currentTimeMillis()+"\\");
		if(!f.exists()){
			f.mkdir();
		}
		//generate gramar in temp folder 
		HashMap<String, String > map = writeToFile(f);
		CompileGrammar.generateJavas(f.getPath()+"\\"+Proprietati.grammarFile+".g",f.getPath());
		ReplaceInFile.replaceInFile(f.getPath()+"\\"+Proprietati.grammarFile+"Parser.java", map);
		HashMap<String, String> rep = new HashMap<String, String>();
		rep.put("#grammar",Proprietati.grammarFile);
		rep.put("#functionName", topFunction);
		ReplaceInFile.replaceInFile(Proprietati.templateFile, f.getPath()+"\\Main.java", rep);
		CompileGrammar.compileClasses(f.getPath()+"\\*.java",f.getPath());
		//jar cvfe impSSAst.jar Main *.class
		createManifestFile(f);
		copyDirectory(new File (f.getParent()+"\\antlr"), new File(f.getPath()+"\\antlr"));
		copyDirectory(new File (f.getParent()+"\\org"), new File(f.getPath()+"\\org"));
		String command = Proprietati.javaJar+" cfm \""+file.getPath()+"\\"+Proprietati.grammarFile+".jar\" "+f.getPath()+"\\MANIFEST.MF *" ;
		System.out.println(command);
		Process p = Runtime.getRuntime().exec(command,null,f);
		BufferedReader is = new BufferedReader(new InputStreamReader(p.getErrorStream()));
		// String line;
		// while ((line = is.readLine()) != null)
		//   System.out.println(line);

		//System.out.flush();
		try {
			System.out.println(p.waitFor());
			System.out.println(p.exitValue());
		} catch (InterruptedException ex) {
			Logger.getLogger(CompileGrammar.class.getName()).log(Level.SEVERE, null, ex);
		}
		f.delete();
		//CompileGrammar.compileClasses(System.getProperty("java.io.tmpdir")+"outputJava\\"+Properties.grammarFile+"Lexer.java",System.getProperty("java.io.tmpdir")+"outputJava\\bin\\");
		//CompileGrammar.compileClasses(System.getProperty("java.io.tmpdir")+"outputJava\\"+Properties.grammarFile+"Parser.java",System.getProperty("java.io.tmpdir")+"outputJava\\bin\\");
	}

	public static void createManifestFile (File f ) throws IOException{
		BufferedWriter out = new BufferedWriter(new FileWriter(f.getPath()+"\\MANIFEST.MF"));
		out.write("Class-Path: antlr-3.4-complete.jar\n");
		out.write("Main-Class: Main\n");
		out.write("\n");
		out.flush();
		out.close();

	}

	public static int countDesc(TreeNode node){
		if (node == null)
			return 0 ;
		int desc = node.getChildCount() ;
		for (int i = 0 ;  i < node.getChildCount() ; i++)
			desc = desc + countDesc(node.getChild(i));
		return desc;
	}

	public static boolean isRecursive(String rule) {
		if (!rule.contains("*"))
			return false;
		if (rule.contains("'*'"))
			return false;
		return true;
	}

	public static boolean checkCoveredSubRules(){
		for (AntlrRule r : orderedRuleList){
			for (int i = 0 ; i < r.getSubRules().length;i++){
				if (r.getSubRules()[i].contains("'") && (!isRecursive(r.getSubRules()[i]))){
					if (r.getLabels().get(i).equals(""))
						return false;
				}
			}
		}
		return true;
	}



	public static void printTree(TreeNode t, int indent) {
		if (t != null) {
			StringBuffer sb = new StringBuffer(indent);
			for (int i = 0; i < indent; i++) {
				sb = sb.append("   ");
			}
			for (int i = 0; i < t.getChildCount(); i++) {
				System.out.println(sb.toString() + t.getChild(i).toString());
				printTree(t.getChild(i), indent + 1);
			}
		}
	}

	public static String stringTree(TreeNode t, int indent) {
		StringBuilder rez = new StringBuilder();
		// rez.append(t.getLabel());
		if (t != null) {
			StringBuffer sb = new StringBuffer(indent);
			for (int i = 0; i < indent; i++) {
				sb = sb.append("   ");
			}
			for (int i = 0; i < t.getChildCount(); i++) {
				rez.append(sb.toString()).append(t.getChild(i).toString()).append("\n");
				rez.append(stringTree(t.getChild(i), indent + 1));
			}
		}
		return rez.toString();
	}

}
